#pragma once
#include <map>
#include "VirtualProfileFwd.h"
#include "VirtualLocationFwd.h"
#include "FileStream.h"
#include "ILocationFwd.h"
#include "Hash.h"
#include "VirtualLocation.h"
#include "ImportExport.h"

namespace ja2{ namespace vfs
{
	class ILocation;
	class CProfileStack;

	//! Virtual file system.
	class VirtualFileSystem : boost::noncopyable
	{
		// Typedefs
	private:
		typedef std::unordered_map<boost::filesystem::path, VirtualLocationPtr_t, hash_path> VirtualLocationMap_t;
		typedef std::map<std::string, VirtualProfilePtr_t> VirtualProfileMap_t;

		// Inner classes
	public:
		class RegularIterator;
		class MatchingIterator;

		// Attributes
	private:
		//! Virtual location map.
		VirtualLocationMap_t m_LocationMap;
		//! Map of all profiles.
		VirtualProfileMap_t m_ProfileMap;
		
		// Operations
	public:
		//! Add new location.
		JA2_VFS_API void add_location(ILocationPtr_t &&pLocation, std::string const &ProfileName, bool IsWritable);
		//! Find if file exist.
		JA2_VFS_API bool file_exists(boost::filesystem::path const &FilePath) const;
		//! Find if file exist in selected profile.
		JA2_VFS_API bool file_exists(boost::filesystem::path const &FilePath, std::string const &ProfileName) const;
		//! Get file from profile.
		JA2_VFS_API FileProxy open_file(boost::filesystem::path const &FilePath, std::string const &ProfileName) const;
		//! Get file from virtual location.
		JA2_VFS_API FileProxy open_file(boost::filesystem::path const &FilePath) const;
		//! Get virtual location for selected path. /return borowed pointer.
		JA2_VFS_API VirtualLocation *get_virtual_location(boost::filesystem::path const &Path) const;
		//! Get virtual location for selected path. If location doesn't exist, create one. /return borowed pointer.
		JA2_VFS_API VirtualLocation *get_create_virtual_location(boost::filesystem::path const &Path, bool IsExclusive);
		//! Create virtual location.
		JA2_VFS_API void create_virtual_location(boost::filesystem::path const &Path, bool IsExclusive);
		//! Virtual location exist.
		JA2_VFS_API bool virtual_location_exist(boost::filesystem::path const &Path) const;
		//! Profile exist.
		JA2_VFS_API bool profile_exists(std::string const &Profile) const;
		//! Create new profile. /return borrowed pointer.
		JA2_VFS_API VirtualProfile *create_profile(std::string const &Name, bool Writeable);
		//! Get virtual profile. /return borrowed pointer.
		JA2_VFS_API VirtualProfile *get_profile(std::string const &Name) const;
		//! Get instance.
		static JA2_VFS_API VirtualFileSystem *instance();
	};

} /*ja2*/} /*vfs*/
